home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 2 / Apprentice-Release2.iso / Source Code / C / Games / NetHack 3.1.3 / source / win / tty / termcap.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-08-01  |  21.5 KB  |  1,038 lines  |  [TEXT/R*ch]

  1. /*    SCCS Id: @(#)termcap.c    3.1    92/11/15    */
  2. /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
  3. /* NetHack may be freely redistributed.  See license for details. */
  4.  
  5. #include "hack.h"
  6.  
  7. #if defined (TTY_GRAPHICS) && !defined(NO_TERMS)
  8.  
  9. #include "wintty.h"
  10.  
  11. #include "termcap.h"
  12.  
  13.  
  14. #ifdef MICROPORT_286_BUG
  15. #define Tgetstr(key) (tgetstr(key,tbuf))
  16. #else
  17. #define Tgetstr(key) (tgetstr(key,&tbufptr))
  18. #endif /* MICROPORT_286_BUG **/
  19.  
  20. static char * FDECL(s_atr2str, (int));
  21. static char * FDECL(e_atr2str, (int));
  22.  
  23. void FDECL(cmov, (int, int));
  24. void FDECL(nocmov, (int, int));
  25. #if defined(TEXTCOLOR) && defined(TERMLIB)
  26. # ifdef OVLB
  27. #  if !defined(UNIX) || !defined(TERMINFO)
  28. #   ifndef TOS
  29. static void FDECL(analyze_seq, (char *, int *, int *));
  30. #   endif
  31. #  endif
  32. static void NDECL(init_hilite);
  33. # endif /* OVLB */
  34. #endif
  35.  
  36. #ifdef OVLB
  37.     /* (see termcap.h) -- CM, ND, CD, HI,HE, US,UE, ul_hack */
  38. struct tc_lcl_data tc_lcl_data = { 0, 0, 0, 0,0, 0,0, FALSE };
  39. #endif /* OVLB */
  40.  
  41. STATIC_VAR char *HO, *CL, *CE, *UP, *XD, *BC, *SO, *SE, *TI, *TE;
  42. STATIC_VAR char *VS, *VE;
  43. #if 0
  44. STATIC_VAR char *MR, *ME;
  45. STATIC_VAR char *MB, *MH;
  46. STATIC_VAR char *MD;     /* may already be in use below */
  47. #endif
  48. #ifdef TERMLIB
  49. # ifdef TEXTCOLOR
  50. STATIC_VAR char *MD;
  51. # endif
  52. STATIC_VAR int SG;
  53. #ifdef OVLB
  54. STATIC_OVL char PC = '\0';
  55. #else /* OVLB */
  56. STATIC_DCL char PC;
  57. #endif /* OVLB */
  58. STATIC_VAR char tbuf[512];
  59. #endif
  60.  
  61. #ifdef TEXTCOLOR
  62. # ifdef TOS
  63. const char *hilites[MAXCOLORS];    /* terminal escapes for the various colors */
  64. # else
  65. char NEARDATA *hilites[MAXCOLORS]; /* terminal escapes for the various colors */
  66. # endif
  67. #endif
  68.  
  69. #ifdef OVLB
  70. static char *KS = NULL, *KE = NULL;    /* keypad sequences */
  71. static char nullstr[] = "";
  72. #endif /* OVLB */
  73.  
  74. #ifndef TERMLIB
  75. STATIC_VAR char tgotobuf[20];
  76. # ifdef TOS
  77. #define tgoto(fmt, x, y)    (Sprintf(tgotobuf, fmt, y+' ', x+' '), tgotobuf)
  78. # else
  79. #define tgoto(fmt, x, y)    (Sprintf(tgotobuf, fmt, y+1, x+1), tgotobuf)
  80. # endif
  81. #endif /* TERMLIB */
  82.  
  83. #ifdef OVLB
  84.  
  85. void
  86. tty_startup(wid, hgt)
  87. int *wid, *hgt;
  88. {
  89.     register int i;
  90. #ifdef TERMLIB
  91.     register const char *term;
  92.     register char *tptr;
  93.     char *tbufptr, *pc;
  94.  
  95. # ifdef VMS
  96.     term = verify_termcap();
  97.     if (!term)
  98. # endif
  99.         term = getenv("TERM");
  100.  
  101. # if defined(TOS) && defined(__GNUC__)
  102.     if (!term)
  103.         term = "builtin";        /* library has a default */
  104. # endif
  105.     if (!term)
  106. #endif
  107. #ifndef ANSI_DEFAULT
  108.         error("Can't get TERM.");
  109. #else
  110. # ifdef TOS
  111.     {
  112.         CO = 80; LI = 25;
  113.         TI = VS = VE = TE = nullstr;
  114.         HO = "\033H";
  115.         CE = "\033K";        /* the VT52 termcap */
  116.         UP = "\033A";
  117.         CM = "\033Y%c%c";    /* used with function tgoto() */
  118.         ND = "\033C";
  119.         XD = "\033B";
  120.         BC = "\033D";
  121.         SO = "\033p";
  122.         SE = "\033q";
  123.     /* HI and HE will be updated in init_hilite if we're using color */
  124.         HI = "\033p";
  125.         HE = "\033q";
  126.         *wid = CO;
  127.         *hgt = LI;
  128.         CL = "\033E";        /* last thing set */
  129.         return;
  130.     }
  131. # else /* TOS */
  132.     {
  133. #  ifdef MICRO
  134.         get_scr_size();
  135. #   ifdef CLIPPING
  136.         if(CO < COLNO || LI < ROWNO+3)
  137.             setclipped();
  138. #   endif
  139. #  endif
  140.         HO = "\033[H";
  141. /*        CD = "\033[J"; */
  142.         CE = "\033[K";        /* the ANSI termcap */
  143. #  ifndef TERMLIB
  144.         CM = "\033[%d;%dH";
  145. #  else
  146.         CM = "\033[%i%d;%dH";
  147. #  endif
  148.         UP = "\033[A";
  149.         ND = "\033[C";
  150.         XD = "\033[B";
  151. #  ifdef MICRO    /* backspaces are non-destructive */
  152.         BC = "\b";
  153. #  else
  154.         BC = "\033[D";
  155. #  endif
  156.         HI = SO = "\033[1m";
  157.         US = "\033[4m";
  158. #  if 0
  159.         MR = "\033[7m";
  160.         ME = "\033[0m";
  161. #  endif
  162.         TI = HE = SE = UE = "\033[0m";
  163.         /* strictly, SE should be 2, and UE should be 24,
  164.            but we can't trust all ANSI emulators to be
  165.            that complete.  -3. */
  166. #  ifndef MICRO
  167.         AS = "\016";
  168.         AE = "\017";
  169. #  endif
  170.         TE = VS = VE = nullstr;
  171. #  ifdef TEXTCOLOR
  172.         for (i = 0; i < MAXCOLORS / 2; i++)
  173.             if (i != BLACK) {
  174.             hilites[i|BRIGHT] = (char *) alloc(sizeof("\033[1;3%dm"));
  175.             Sprintf(hilites[i|BRIGHT], "\033[1;3%dm", i);
  176.             if (i != GRAY)
  177. #   ifdef MICRO
  178.                 if (i == BLUE) hilites[BLUE] = hilites[BLUE|BRIGHT];
  179.                 else
  180. #   endif
  181.                 {
  182.                 hilites[i] = (char *) alloc(sizeof("\033[0;3%dm"));
  183.                 Sprintf(hilites[i], "\033[0;3%dm", i);
  184.                 }
  185.             }
  186. #  endif
  187.         *wid = CO;
  188.         *hgt = LI;
  189.         CL = "\033[2J";        /* last thing set */
  190.         return;
  191.     }
  192. # endif /* TOS */
  193. #endif /* ANSI_DEFAULT */
  194.  
  195. #ifdef TERMLIB
  196.     tptr = (char *) alloc(1024);
  197.  
  198.     tbufptr = tbuf;
  199.     if(!strncmp(term, "5620", 4))
  200.         flags.null = FALSE;    /* this should be a termcap flag */
  201.     if(tgetent(tptr, term) < 1)
  202.         error("Unknown terminal type: %s.", term);
  203.     if ((pc = Tgetstr("pc")) != 0)
  204.         PC = *pc;
  205.  
  206.     if(!(BC = Tgetstr("le")))    /* both termcap and terminfo use le */    
  207. # ifdef TERMINFO
  208.         error("Terminal must backspace.");
  209. # else
  210.         if(!(BC = Tgetstr("bc"))) {    /* termcap also uses bc/bs */
  211. #  ifndef MINIMAL_TERM
  212.         if(!tgetflag("bs"))
  213.             error("Terminal must backspace.");
  214. #  endif
  215.         BC = tbufptr;
  216.         tbufptr += 2;
  217.         *BC = '\b';
  218.         }
  219. # endif
  220.  
  221. # ifdef MINIMAL_TERM
  222.     HO = NULL;
  223. # else
  224.     HO = Tgetstr("ho");
  225. # endif
  226.     /*
  227.      * LI and CO are set in ioctl.c via a TIOCGWINSZ if available.  If
  228.      * the kernel has values for either we should use them rather than
  229.      * the values from TERMCAP ...
  230.      */
  231. # ifndef MICRO
  232.     if (!CO) CO = tgetnum("co");
  233.     if (!LI) LI = tgetnum("li");
  234. # else
  235. #  if defined(TOS) && defined(__GNUC__)
  236.     if (!strcmp(term, "builtin"))
  237.         get_scr_size();
  238.     else {
  239. #  endif
  240.         CO = tgetnum("co");
  241.         LI = tgetnum("li");
  242.         if (!LI || !CO)            /* if we don't override it */
  243.             get_scr_size();
  244. #  if defined(TOS) && defined(__GNUC__)
  245.     }
  246. #  endif
  247. # endif
  248. # ifdef CLIPPING
  249.     if(CO < COLNO || LI < ROWNO+3)
  250.         setclipped();
  251. # endif
  252.     ND = Tgetstr("nd");
  253.     if(tgetflag("os"))
  254.         error("NetHack can't have OS.");
  255.     if(tgetflag("ul"))
  256.         ul_hack = TRUE;
  257.     CE = Tgetstr("ce");
  258.     UP = Tgetstr("up");
  259.     /* It seems that xd is no longer supported, and we should use
  260.        a linefeed instead; unfortunately this requires resetting
  261.        CRMOD, and many output routines will have to be modified
  262.        slightly. Let's leave that till the next release. */
  263.     XD = Tgetstr("xd");
  264. /* not:         XD = Tgetstr("do"); */
  265.     if(!(CM = Tgetstr("cm"))) {
  266.         if(!UP && !HO)
  267.         error("NetHack needs CM or UP or HO.");
  268.         tty_raw_print("Playing NetHack on terminals without CM is suspect.");
  269.         tty_wait_synch();
  270.     }
  271.     SO = Tgetstr("so");
  272.     SE = Tgetstr("se");
  273.     US = Tgetstr("us");
  274.     UE = Tgetstr("ue");
  275.     SG = tgetnum("sg");    /* -1: not fnd; else # of spaces left by so */
  276.     if(!SO || !SE || (SG > 0)) SO = SE = US = UE = nullstr;
  277.     TI = Tgetstr("ti");
  278.     TE = Tgetstr("te");
  279.     VS = VE = nullstr;
  280. # ifdef TERMINFO
  281.     VS = Tgetstr("eA");    /* enable graphics */
  282. # endif
  283.     KS = Tgetstr("ks");    /* keypad start (special mode) */
  284.     KE = Tgetstr("ke");    /* keypad end (ordinary mode [ie, digits]) */
  285. # if 0
  286.     MR = Tgetstr("mr");    /* reverse */
  287.     MB = Tgetstr("mb");    /* blink */
  288.     MD = Tgetstr("md");    /* boldface */
  289.     MH = Tgetstr("mh");    /* dim */
  290.     ME = Tgetstr("me");
  291. # endif
  292.  
  293.     /* Get rid of padding numbers for HI and HE.  Hope they
  294.      * aren't really needed!!!  HI and HE are ouputted to the
  295.      * pager as a string - so how can you send it NULLS???
  296.      *  -jsb
  297.      */
  298.         HI = (char *) alloc((unsigned)(strlen(SO)+1));
  299.         HE = (char *) alloc((unsigned)(strlen(SE)+1));
  300.         i = 0;
  301.         while (digit(SO[i])) i++;
  302.         Strcpy(HI, &SO[i]);
  303.         i = 0;
  304.         while (digit(SE[i])) i++;
  305.         Strcpy(HE, &SE[i]);
  306.     AS = Tgetstr("as");
  307.     AE = Tgetstr("ae");
  308.     CD = Tgetstr("cd");
  309. # ifdef TEXTCOLOR
  310.     MD = Tgetstr("md");
  311. # endif
  312. # ifdef TEXTCOLOR
  313. #  if defined(TOS) && defined(__GNUC__)
  314.     if (!strcmp(term, "builtin") || !strcmp(term, "tw52") ||
  315.         !strcmp(term, "st52")) {
  316.         init_hilite();
  317.     }
  318. #  else
  319.     init_hilite();
  320. #  endif
  321. # endif
  322.     *wid = CO;
  323.     *hgt = LI;
  324.     if (!(CL = Tgetstr("cl")))    /* last thing set */
  325.         error("NetHack needs CL.");
  326.     if(tbufptr-tbuf > sizeof(tbuf)) error("TERMCAP entry too big...\n");
  327.     free((genericptr_t)tptr);
  328. #endif /* TERMLIB */
  329. }
  330.  
  331. void
  332. tty_number_pad(state)
  333. int state;
  334. {
  335.     switch (state) {
  336.         case -1:    /* activate keypad mode (escape sequences) */
  337.             if (KS && *KS) xputs(KS);
  338.             break;
  339.         case  1:    /* activate numeric mode for keypad (digits) */
  340.             if (KE && *KE) xputs(KE);
  341.             break;
  342.         case  0:    /* don't need to do anything--leave terminal as-is */
  343.         default:
  344.             break;
  345.     }
  346. }
  347.  
  348. #ifdef TERMLIB
  349. extern void NDECL((*decgraphics_mode_callback));    /* defined in drawing.c */
  350. static void NDECL(tty_decgraphics_termcap_fixup);
  351.  
  352. /*
  353.    We call this routine whenever DECgraphics mode is enabled, even if it
  354.    has been previously set, in case the user manages to reset the fonts.
  355.    The actual termcap fixup only needs to be done once, but we can't
  356.    call xputs() from the option setting or graphics assigning routines,
  357.    so this is a convenient hook.
  358.  */
  359. static void
  360. tty_decgraphics_termcap_fixup()
  361. {
  362.     static char ctrlN[]   = "\016";
  363.     static char ctrlO[]   = "\017";
  364.     static char appMode[] = "\033=";
  365.     static char numMode[] = "\033>";
  366.  
  367.     /* these values are missing from some termcaps */
  368.     if (!AS) AS = ctrlN;    /* ^N (shift-out [graphics font]) */
  369.     if (!AE) AE = ctrlO;    /* ^O (shift-in  [regular font])  */
  370.     if (!KS) KS = appMode;    /* ESC= (application keypad mode) */
  371.     if (!KE) KE = numMode;    /* ESC> (numeric keypad mode)      */
  372.     /*
  373.      * Select the line-drawing character set as the alternate font.
  374.      * Do not select NA ASCII as the primary font since people may
  375.      * reasonably be using the UK character set.
  376.      */
  377. #ifdef PC9801
  378.     init_hilite();
  379. #endif
  380.     if (flags.DECgraphics) xputs("\033)0");
  381. }
  382. #endif
  383.  
  384. #if defined(ASCIIGRAPH) && defined(PC9801)
  385. extern void NDECL((*ibmgraphics_mode_callback));    /* defined in drawing.c */
  386. #endif
  387.  
  388. #ifdef PC9801
  389. extern void NDECL((*ascgraphics_mode_callback));    /* defined in drawing.c */
  390. static void NDECL(tty_ascgraphics_hilite_fixup);
  391.  
  392. static void
  393. tty_ascgraphics_hilite_fixup()
  394. {
  395.     register int c;
  396.  
  397.     for (c = 0; c < MAXCOLORS / 2; c++)
  398.     if (c != BLACK) {
  399.         hilites[c|BRIGHT] = (char *) alloc(sizeof("\033[1;3%dm"));
  400.         Sprintf(hilites[c]BRIGHT], "\033[1;3%dm", c);
  401.         if (c != GRAY) {
  402.             hilites[c] = (char *) alloc(sizeof("\033[0;3%dm"));
  403.             Sprintf(hilites[c], "\033[0;3%dm", c);
  404.         }
  405.     }
  406. }
  407. #endif /* PC9801 */
  408.  
  409. void
  410. tty_start_screen()
  411. {
  412.     xputs(TI);
  413.     xputs(VS);
  414. #ifdef PC9801
  415.     if (!flags.IBMgraphics && !flags.DECgraphics)
  416.         tty_ascgraphics_hilite_fixup();
  417.     /* set up callback in case option is not set yet but toggled later */
  418.     ascgraphics_mode_callback = tty_ascgraphics_hilite_fixup;
  419. # ifdef ASCIIGRAPH
  420.     if (flags.IBMgraphics) init_hilite();
  421.     /* set up callback in case option is not set yet but toggled later */
  422.     ibmgraphics_mode_callback = init_hilite;
  423. # endif
  424. #endif /* PC9801 */
  425.  
  426. #ifdef TERMLIB
  427.     if (flags.DECgraphics) tty_decgraphics_termcap_fixup();
  428.     /* set up callback in case option is not set yet but toggled later */
  429.     decgraphics_mode_callback = tty_decgraphics_termcap_fixup;
  430. #endif
  431.     if (flags.num_pad) tty_number_pad(1);    /* make keypad send digits */
  432. }
  433.  
  434. void
  435. tty_end_screen()
  436. {
  437.     clear_screen();
  438.     xputs(VE);
  439.     xputs(TE);
  440. }
  441.  
  442. /* Cursor movements */
  443.  
  444. #endif /* OVLB */
  445.  
  446. #ifdef OVL0
  447. /* Note to OVLx tinkerers.  The placement of this overlay controls the location
  448.    of the function xputc().  This function is not currently in trampoli.[ch]
  449.    files for what is deemed to be performance reasons.  If this define is moved
  450.    and or xputc() is taken out of the ROOT overlay, then action must be taken
  451.    in trampoli.[ch]. */
  452.  
  453. void
  454. nocmov(x, y)
  455. int x,y;
  456. {
  457.     if ((int) ttyDisplay->cury > y) {
  458.         if(UP) {
  459.             while ((int) ttyDisplay->cury > y) {    /* Go up. */
  460.                 xputs(UP);
  461.                 ttyDisplay->cury--;
  462.             }
  463.         } else if(CM) {
  464.             cmov(x, y);
  465.         } else if(HO) {
  466.             home();
  467.             tty_curs(BASE_WINDOW, x+1, y);
  468.         } /* else impossible("..."); */
  469.     } else if ((int) ttyDisplay->cury < y) {
  470.         if(XD) {
  471.             while((int) ttyDisplay->cury < y) {
  472.                 xputs(XD);
  473.                 ttyDisplay->cury++;
  474.             }
  475.         } else if(CM) {
  476.             cmov(x, y);
  477.         } else {
  478.             while((int) ttyDisplay->cury < y) {
  479.                 xputc('\n');
  480.                 ttyDisplay->curx = 0;
  481.                 ttyDisplay->cury++;
  482.             }
  483.         }
  484.     }
  485.     if ((int) ttyDisplay->curx < x) {        /* Go to the right. */
  486.         if(!ND) cmov(x, y); else    /* bah */
  487.             /* should instead print what is there already */
  488.         while ((int) ttyDisplay->curx < x) {
  489.             xputs(ND);
  490.             ttyDisplay->curx++;
  491.         }
  492.     } else if ((int) ttyDisplay->curx > x) {
  493.         while ((int) ttyDisplay->curx > x) {    /* Go to the left. */
  494.             xputs(BC);
  495.             ttyDisplay->curx--;
  496.         }
  497.     }
  498. }
  499.  
  500. void
  501. cmov(x, y)
  502. register int x, y;
  503. {
  504.     xputs(tgoto(CM, x, y));
  505.     ttyDisplay->cury = y;
  506.     ttyDisplay->curx = x;
  507. }
  508.  
  509. /* See note at OVLx ifdef above.   xputc() is a special function. */
  510. void
  511. xputc(c)
  512. #if defined(apollo)
  513. int c;
  514. #else
  515. char c;
  516. #endif
  517. {
  518.     (void) putchar(c);
  519. }
  520.  
  521. void
  522. xputs(s)
  523. const char *s;
  524. {
  525. # ifndef TERMLIB
  526.     (void) fputs(s, stdout);
  527. # else
  528. #  if defined(NHSTDC) || defined(ULTRIX_PROTO)
  529.     tputs(s, 1, (int (*)())xputc);
  530. #  else
  531.     tputs(s, 1, xputc);
  532. #  endif
  533. # endif
  534. }
  535.  
  536. void
  537. cl_end()
  538. {
  539.     if(CE)
  540.         xputs(CE);
  541.     else {    /* no-CE fix - free after Harold Rynes */
  542.         /* this looks terrible, especially on a slow terminal
  543.            but is better than nothing */
  544.         register int cx = ttyDisplay->curx+1;
  545.  
  546.         while(cx < CO) {
  547.             xputc(' ');
  548.             cx++;
  549.         }
  550.         tty_curs(BASE_WINDOW, (int)ttyDisplay->curx+1,
  551.                         (int)ttyDisplay->cury);
  552.     }
  553. }
  554.  
  555. #endif /* OVL0 */
  556. #ifdef OVLB
  557.  
  558. void
  559. clear_screen()
  560. {
  561.     /* note: if CL is null, then termcap initialization failed,
  562.         so don't attempt screen-oriented I/O during final cleanup.
  563.      */
  564.     if (CL) {
  565.         xputs(CL);
  566.         home();
  567.     }
  568. }
  569.  
  570. #endif /* OVLB */
  571. #ifdef OVL0
  572.  
  573. void
  574. home()
  575. {
  576.     if(HO)
  577.         xputs(HO);
  578.     else if(CM)
  579.         xputs(tgoto(CM, 0, 0));
  580.     else
  581.         tty_curs(BASE_WINDOW, 1, 0);    /* using UP ... */
  582.     ttyDisplay->curx = ttyDisplay->cury = 0;
  583. }
  584.  
  585. void
  586. standoutbeg()
  587. {
  588.     if(SO) xputs(SO);
  589. }
  590.  
  591. void
  592. standoutend()
  593. {
  594.     if(SE) xputs(SE);
  595. }
  596.  
  597. #if 0    /* if you need one of these, uncomment it (here and in extern.h) */
  598. void
  599. revbeg()
  600. {
  601.     if(MR) xputs(MR);
  602. }
  603.  
  604. void
  605. boldbeg()
  606. {
  607.     if(MD) xputs(MD);
  608. }
  609.  
  610. void
  611. blinkbeg()
  612. {
  613.     if(MB) xputs(MB);
  614. }
  615.  
  616. void
  617. dimbeg()
  618. /* not in most termcap entries */
  619. {
  620.     if(MH) xputs(MH);
  621. }
  622.  
  623. void
  624. m_end()
  625. {
  626.     if(ME) xputs(ME);
  627. }
  628. #endif
  629.  
  630. #endif /* OVL0 */
  631. #ifdef OVLB
  632.  
  633. void
  634. backsp()
  635. {
  636.     xputs(BC);
  637. }
  638.  
  639. void
  640. tty_nhbell()
  641. {
  642.     if (flags.silent) return;
  643.     (void) putchar('\007');        /* curx does not change */
  644.     (void) fflush(stdout);
  645. }
  646.  
  647. #endif /* OVLB */
  648. #ifdef OVL0
  649.  
  650. #ifdef ASCIIGRAPH
  651. void
  652. graph_on() {
  653.     if (AS) xputs(AS);
  654. }
  655.  
  656. void
  657. graph_off() {
  658.     if (AE) xputs(AE);
  659. }
  660. #endif
  661.  
  662. #endif /* OVL0 */
  663. #ifdef OVL1
  664.  
  665. #if !defined(MICRO)
  666. # ifdef VMS
  667. static const short tmspc10[] = {        /* from termcap */
  668.     0, 2000, 1333, 909, 743, 666, 333, 166, 83, 55, 50, 41, 27, 20, 13, 10,
  669.     5
  670. };
  671. # else
  672. static const short tmspc10[] = {        /* from termcap */
  673.     0, 2000, 1333, 909, 743, 666, 500, 333, 166, 83, 55, 41, 20, 10, 5
  674. };
  675. # endif
  676. #endif
  677.  
  678. void
  679. tty_delay_output()
  680. {
  681.     /* delay 50 ms - could also use a 'nap'-system call */
  682.     /* BUG: if the padding character is visible, as it is on the 5620
  683.        then this looks terrible. */
  684. #if defined(MICRO)
  685.     /* simulate the delay with "cursor here" */
  686.     register int i;
  687.     for (i = 0; i < 3; i++) {
  688.         cmov(ttyDisplay->curx, ttyDisplay->cury);
  689.         (void) fflush(stdout);
  690.     }
  691. #else /* MICRO */
  692.     if(flags.null)
  693. # ifdef TERMINFO
  694.         /* cbosgd!cbcephus!pds for SYS V R2 */
  695. #  ifdef NHSTDC
  696.         tputs("$<50>", 1, (int (*)())xputc);
  697. #  else
  698.         tputs("$<50>", 1, xputc);
  699. #  endif
  700. # else
  701. #  if defined(NHSTDC) || defined(ULTRIX_PROTO)
  702.         tputs("50", 1, (int (*)())xputc);
  703. #  else
  704.         tputs("50", 1, xputc);
  705. #  endif
  706. # endif
  707.  
  708.     else if(ospeed > 0 && ospeed < SIZE(tmspc10)) if(CM) {
  709.         /* delay by sending cm(here) an appropriate number of times */
  710.         register int cmlen = strlen(tgoto(CM, ttyDisplay->curx, ttyDisplay->cury));
  711.         register int i = 500 + tmspc10[ospeed]/2;
  712.  
  713.         while(i > 0) {
  714.             cmov((int)ttyDisplay->curx, (int)ttyDisplay->cury);
  715.             i -= cmlen*tmspc10[ospeed];
  716.         }
  717.     }
  718. #endif /* MICRO */
  719. }
  720.  
  721. #endif /* OVL1 */
  722. #ifdef OVLB
  723.  
  724. void
  725. cl_eos()            /* free after Robert Viduya */
  726. {                /* must only be called with curx = 1 */
  727.  
  728.     if(CD)
  729.         xputs(CD);
  730.     else {
  731.         register int cy = ttyDisplay->cury+1;
  732.         while(cy <= LI-2) {
  733.             cl_end();
  734.             xputc('\n');
  735.             cy++;
  736.         }
  737.         cl_end();
  738.         tty_curs(BASE_WINDOW, (int)ttyDisplay->curx+1,
  739.                         (int)ttyDisplay->cury);
  740.     }
  741. }
  742.  
  743. #if defined(TEXTCOLOR) && defined(TERMLIB)
  744. # if defined(UNIX) && defined(TERMINFO)
  745. /*
  746.  * Sets up color highlighting, using terminfo(4) escape sequences (highlight
  747.  * code found in print.c).  It is assumed that the background color is black.
  748.  */
  749. /* terminfo indexes for the basic colors it guarantees */
  750. #define COLOR_BLACK   1        /* fake out to avoid black on black */
  751. #define COLOR_BLUE    1
  752. #define COLOR_GREEN   2
  753. #define COLOR_CYAN    3
  754. #define COLOR_RED     4
  755. #define COLOR_MAGENTA 5
  756. #define COLOR_YELLOW  6
  757. #define COLOR_WHITE   7
  758.  
  759. /* map ANSI RGB to terminfo BGR */
  760. const int ti_map[8] = {
  761.     COLOR_BLACK, COLOR_RED, COLOR_GREEN, COLOR_YELLOW,
  762.     COLOR_BLUE, COLOR_MAGENTA, COLOR_CYAN, COLOR_WHITE };
  763.  
  764. static void
  765. init_hilite()
  766. {
  767.     register int c;
  768.     char *setf, *scratch;
  769.     extern char *tparm();
  770.  
  771.     for (c = 0; c < SIZE(hilites); c++)
  772.         hilites[c] = HI;
  773.     hilites[GRAY] = hilites[NO_COLOR] = NULL;
  774.  
  775.     if (tgetnum("Co") < 8 || (setf = tgetstr("Sf", (char **)0)) == NULL)
  776.         return;
  777.  
  778.     for (c = 0; c < MAXCOLORS / 2; c++) {
  779.           scratch = tparm(setf, ti_map[c]);
  780.         if (c != GRAY) {
  781.             hilites[c] = (char *) alloc(strlen(scratch) + 1);
  782.             Strcpy(hilites[c], scratch);
  783.         }
  784.         if (c != BLACK) {
  785.             hilites[c|BRIGHT] = (char*) alloc(strlen(scratch)+strlen(MD)+1);
  786.             Strcpy(hilites[c|BRIGHT], MD);
  787.             Strcat(hilites[c|BRIGHT], scratch);
  788.             }
  789.         
  790.     }
  791. }
  792.  
  793. # else /* UNIX && TERMINFO */
  794.  
  795. #  ifndef TOS
  796. /* find the foreground and background colors set by HI or HE */
  797. static void
  798. analyze_seq (str, fg, bg)
  799. char *str;
  800. int *fg, *bg;
  801. {
  802.     register int c, code;
  803.     int len;
  804.  
  805. #   ifdef MICRO
  806.     *fg = GRAY; *bg = BLACK;
  807. #   else
  808.     *fg = *bg = NO_COLOR;
  809. #   endif
  810.  
  811.     if (str[0] != '\033' || str[1] != '[' ||
  812.         str[len = strlen(str) - 1] != 'm' || len < 3)
  813.         return;
  814.  
  815.     c = 2;
  816.     while (c < len) {
  817.         if ((code = atoi(&str[c])) == 0) { /* reset */
  818.         /* this also catches errors */
  819. #   ifdef MICRO
  820.         *fg = GRAY; *bg = BLACK;
  821. #   else
  822.         *fg = *bg = NO_COLOR;
  823. #   endif
  824.         } else if (code == 1) { /* bold */
  825.         *fg |= BRIGHT;
  826. #   if 0
  827.     /* I doubt we'll ever resort to using blinking characters,
  828.        unless we want a pulsing glow for something.  But, in case
  829.        we do... - 3. */
  830.         } else if (code == 5) { /* blinking */
  831.         *fg |= BLINK;
  832.         } else if (code == 25) { /* stop blinking */
  833.         *fg &= ~BLINK;
  834. #   endif
  835.         } else if (code == 7 || code == 27) { /* reverse */
  836.         code = *fg & ~BRIGHT;
  837.         *fg = *bg | (*fg & BRIGHT);
  838.         *bg = code;
  839.         } else if (code >= 30 && code <= 37) { /* hi_foreground RGB */
  840.         *fg = code - 30;
  841.         } else if (code >= 40 && code <= 47) { /* hi_background RGB */
  842.         *bg = code - 40;
  843.         }
  844.         while (digit(str[++c]));
  845.         c++;
  846.     }
  847. }
  848. #  endif
  849.  
  850. /*
  851.  * Sets up highlighting sequences, using ANSI escape sequences (highlight code
  852.  * found in print.c).  The HI and HE sequences (usually from SO) is scanned to
  853.  * find foreground and background colors.
  854.  */
  855.  
  856. static void
  857. init_hilite()
  858. {
  859.     register int c;
  860. #  ifdef TOS
  861.     extern unsigned long tos_numcolors;    /* in tos.c */
  862.     static char NOCOL[] = "\033b0", COLHE[] = "\033q\033b0";
  863.  
  864.     if (tos_numcolors <= 2) {
  865.         return;
  866.     }
  867. /* Under TOS, the "bright" and "dim" colors are reversed. Moreover,
  868.  * on the Falcon the dim colors are *really* dim; so we make most
  869.  * of the colors the bright versions, with a few exceptions where
  870.  * the dim ones look OK.
  871.  */
  872.     hilites[0] = NOCOL;
  873.     for (c = 1; c < SIZE(hilites); c++) {
  874.         char *foo;
  875.         foo = (char *) alloc(sizeof("\033b0"));
  876.         if (tos_numcolors > 4)
  877.             Sprintf(foo, "\033b%c", (c&~BRIGHT)+'0');
  878.         else
  879.             Strcpy(foo, "\033b0");
  880.         hilites[c] = foo;
  881.     }
  882.  
  883.     if (tos_numcolors == 4) {
  884.         TI = "\033b0\033c3\033E\033e";
  885.         TE = "\033b3\033c0\033J";
  886.         HE = COLHE;
  887.         hilites[GREEN] = hilites[GREEN|BRIGHT] = "\033b2";
  888.         hilites[RED] = hilites[RED|BRIGHT] = "\033b1";
  889.     } else {
  890.         sprintf(hilites[BROWN], "\033b%c", (BROWN^BRIGHT)+'0');
  891.         sprintf(hilites[GREEN], "\033b%c", (GREEN^BRIGHT)+'0');
  892.  
  893.         TI = "\033b0\033c\017\033E\033e";
  894.         TE = "\033b\017\033c0\033J";
  895.         HE = COLHE;
  896.         hilites[WHITE] = hilites[BLACK] = NOCOL;
  897.         hilites[NO_COLOR] = hilites[GRAY];
  898.     }
  899.  
  900. #  else /* TOS */
  901.  
  902.     int backg, foreg, hi_backg, hi_foreg;
  903.  
  904.      for (c = 0; c < SIZE(hilites); c++)
  905.         hilites[c] = HI;
  906.     hilites[GRAY] = hilites[NO_COLOR] = NULL;
  907.  
  908.     analyze_seq(HI, &hi_foreg, &hi_backg);
  909.     analyze_seq(HE, &foreg, &backg);
  910.  
  911.     for (c = 0; c < SIZE(hilites); c++)
  912.         /* avoid invisibility */
  913.         if ((backg & ~BRIGHT) != c) {
  914. #   ifdef MICRO
  915.         if (c == BLUE) continue;
  916. #   endif
  917.         if (c == foreg)
  918.             hilites[c] = NULL;
  919.         else if (c != hi_foreg || backg != hi_backg) {
  920.             hilites[c] = (char *) alloc(sizeof("\033[%d;3%d;4%dm"));
  921.             Sprintf(hilites[c], "\033[%d", !!(c & BRIGHT));
  922.             if ((c | BRIGHT) != (foreg | BRIGHT))
  923.             Sprintf(eos(hilites[c]), ";3%d", c & ~BRIGHT);
  924.             if (backg != BLACK)
  925.             Sprintf(eos(hilites[c]), ";4%d", backg & ~BRIGHT);
  926.             Strcat(hilites[c], "m");
  927.         }
  928.         }
  929.  
  930. #   ifdef MICRO
  931.     /* brighten low-visibility colors */
  932.     hilites[BLUE] = hilites[BLUE|BRIGHT];
  933. #   endif
  934. #  endif /* TOS */
  935. }
  936. # endif /* UNIX */
  937. #endif /* TEXTCOLOR */
  938.  
  939.  
  940. static char nulstr[] = "";
  941.  
  942. static char *
  943. s_atr2str(n)
  944. int n;
  945. {
  946.     switch (n) {
  947.         case ATR_ULINE:
  948.             if(US) return US;
  949.         case ATR_BOLD:
  950.         case ATR_BLINK:
  951.         case ATR_INVERSE:
  952.             return HI;
  953.     }
  954.     return nulstr;
  955. }
  956.  
  957. static char *
  958. e_atr2str(n)
  959. int n;
  960. {
  961.     switch (n) {
  962.         case ATR_ULINE:
  963.             if(UE) return UE;
  964.         case ATR_BOLD:
  965.         case ATR_BLINK:
  966.         case ATR_INVERSE:
  967.             return HE;
  968.     }
  969.     return nulstr;
  970. }
  971.  
  972.  
  973. void
  974. term_start_attr(attr)
  975. int attr;
  976. {
  977.     if (attr) {
  978.         xputs(s_atr2str(attr));
  979.     }
  980. }
  981.  
  982.         
  983. void
  984. term_end_attr(attr)
  985. int attr;
  986. {
  987.     if(attr) {
  988.         xputs(e_atr2str(attr));
  989.     }
  990. }
  991.  
  992.  
  993. void
  994. term_start_raw_bold()
  995. {
  996.     xputs(HI);
  997. }
  998.  
  999.  
  1000. void
  1001. term_end_raw_bold()
  1002. {
  1003.     xputs(HE);
  1004. }
  1005.  
  1006.  
  1007. #ifdef TEXTCOLOR
  1008.  
  1009. void
  1010. term_end_color()
  1011. {
  1012.     xputs(HE);
  1013. }
  1014.  
  1015.  
  1016. void
  1017. term_start_color(color)
  1018. int color;
  1019. {
  1020.     xputs(hilites[color]);
  1021. }
  1022.  
  1023.  
  1024. int
  1025. has_color(color)
  1026. int color;
  1027. {
  1028.     return hilites[color] != NULL;
  1029. }
  1030.  
  1031. #endif /* TEXTCOLOR */
  1032.  
  1033. #endif /* OVLB */
  1034.  
  1035. #endif /* TTY_GRAPHICS */
  1036.  
  1037. /*termcap.c*/
  1038.